/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.configuration;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.elsfs.cloud.api.security.service.SecurityUserService;
import org.elsfs.cloud.common.security.core.userdetails.SecurityUser;
import org.elsfs.cloud.system.api.entity.SysUser;
import org.elsfs.cloud.system.sys.repository.SysUserRepository;
import org.elsfs.cloud.system.sys.service.SysUserDeptService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**
 * 默认用户服务
 *
 * @author zeng
 */
@Component
@RequiredArgsConstructor
public class SecurityUserServiceImpl implements SecurityUserService<SecurityUser> {
  private final PasswordEncoder passwordEncoder;
  private final SysUserRepository sysUserRepository;
  private final SysUserDeptService sysUserDeptService;

  @Override
  public SecurityUser loadUserByUsername(String username) throws RuntimeException {
    SysUser sysUser = sysUserRepository.getUserByUsername(username);
    return convert(sysUser);
  }

  @Override
  public SecurityUser loadUserByPhone(String phone) throws RuntimeException {
    SysUser sysUser = sysUserRepository.getUserByPhone(phone);
    return convert(sysUser, "手机号未注册");
  }

  @Override
  public SecurityUser loadUserByUserId(String userId) throws RuntimeException {
    SysUser sysUser = sysUserRepository.getById(userId);
    return convert(sysUser);
  }

  @Override
  public SecurityUser loadUserByEmail(String email) throws RuntimeException {
    SysUser sysUser = sysUserRepository.getUserByEmail(email);
    return convert(sysUser, "邮箱未注册");
  }

  @Override
  public SecurityUser geLoginUser() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication instanceof UsernamePasswordAuthenticationToken) {
      return (SecurityUser) authentication.getPrincipal();
    }
    return null;
  }

  @Override
  public SecurityUser loadByUserId(String userId) {
    SysUser sysUser = sysUserRepository.getById(userId);
    return convert(sysUser, "用户id不存在");
  }

  @Override
  public void createUser(UserDetails user) {}

  @Override
  public void updateUser(UserDetails user) {}

  @Override
  public void deleteUser(String username) {}

  @Override
  public void changePassword(String oldPassword, String newPassword) {}

  @Override
  public boolean userExists(String username) {
    return sysUserRepository.getUserByUsername(username) != null;
  }

  private SecurityUser convert(SysUser sysUser) {
    return convert(sysUser, "用户不存在");
  }

  SecurityUser convert(SysUser sysUser, String msg) {
    if (sysUser == null) {
      throw new RuntimeException(msg);
    }
    SecurityUser securityUser = new SecurityUser();
    securityUser.setUserId(sysUser.getUserId());
    securityUser.setUsername(sysUser.getUsername());
    securityUser.setNickname(sysUser.getNickname());
    securityUser.setPassword(sysUser.getPassword());
    securityUser.setEmail(sysUser.getEmail());
    securityUser.setPhone(sysUser.getPhone());
    securityUser.setAvatar(sysUser.getAvatar());
    securityUser.setTenantId(sysUser.getTenantId());
    securityUser.setSex(sysUser.getSex());
    securityUser.setValidFlag(sysUser.getDeleteFlag());
    settingDeptIds(securityUser);
    return securityUser;
  }

  private void settingDeptIds(SecurityUser securityUser) {
    List<String> deptIds = sysUserDeptService.getByUserId(securityUser.getUserId());
    if (deptIds != null && !deptIds.isEmpty()) {
      securityUser.getDeptIds().addAll(deptIds);
    }
  }

  @Override
  public Mono<UserDetails> findByUsername(String username) {
    return Mono.just(loadUserByUsername(username));
  }
}
